package com.qfjg.webcore.auth;


import com.google.gson.Gson;
import com.qfjg.webcore.common.Utils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import net.rubyeye.xmemcached.MemcachedClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;


import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class AuthInterceptor implements HandlerInterceptor {

    @Autowired
    private MemcachedClient memcachedClient;

    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) {
        //拦截器取到请求先进行判断，如果是OPTIONS请求，则放行
        if("OPTIONS".equals(request.getMethod().toUpperCase())) {
            return true;
        }
        Method method = ((HandlerMethod) handler).getMethod();
        try {
            Map<String,String> tokens=new HashMap<>();
            String st=null;
            String ct=null;
            String _t=null;
            String it=null;
            if(Utils.isNullOrEmpty(request.getHeader("st"))){
                st=Utils.uuid();
            }
            else{
                st=request.getHeader("st");
            }
            if(!Utils.isNullOrEmpty(request.getParameter("ct"))) ct=request.getParameter("ct");
            else if(!Utils.isNullOrEmpty(request.getHeader("ct"))) ct=request.getHeader("ct");

            if(!Utils.isNullOrEmpty(request.getParameter("_t"))) _t=request.getParameter("_t");
            else if(!Utils.isNullOrEmpty(request.getHeader("_t"))) _t=request.getHeader("_t");

            if(!Utils.isNullOrEmpty(request.getParameter("it"))) it=request.getParameter("it");
            else if(!Utils.isNullOrEmpty(request.getHeader("it"))) it=request.getHeader("it");

            var realit=(String)memcachedClient.get("it");
            tokens.put("st",st);
            tokens.put("ct",ct);
            tokens.put("_t",_t);
            tokens.put("it",realit);
            request.setAttribute("tokens",tokens);

            if (method.isAnnotationPresent(Pass.class)) return true;

            if (method.isAnnotationPresent(Tokens.class)){
                Tokens ts=method.getAnnotation(Tokens.class);
                if(ts.must_token()==TokenParam.Ct){
                    if(ct==null) response.setStatus(401);
                }

                if(ts.must_token()==TokenParam.It){
                    if(it==null) {
                        response.setStatus(401);
                        return  false;
                    }
                    else{
                        if(realit.equals(it)) return true;
                        else  {
                            response.setStatus(401);
                            return  false;
                        }
                    }
                }


            }

            if(_t!=null){
                var authstr=(String) memcachedClient.get(_t);
                if(authstr==null) {
                    response.setStatus(401);
                    return false;
                }
                else {
                    var auth=new Gson().fromJson(authstr, UserAuth.class);
                    request.setAttribute("userAuth",auth);

                    //检查接口所需权限是否具备
                    if (method.isAnnotationPresent(Perms.class)&&!auth.is_root()) {
                        var permsAttr=method.getAnnotation(Perms.class);
                        for(var i=0;i<permsAttr.perms().length;i++){
                            if(!auth.getPerms().contains(permsAttr.perms()[i])){
                                response.setStatus(401);
                                return false;
                            }
                        }
                    }

                    return true;
                }
            }
        } catch (Exception ignore) {
            response.setStatus(401);
            return false;
        }
        response.setStatus(401);
        return false;
    }
}
